home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 June / EnigmA AMIGA RUN 08 (1996)(G.R. Edizioni)(IT)[!][issue 1996-06][EARSAN CD VII].iso / earcd / gcc / ixemlsrc.lha / ixemul / utils / zic.c < prev   
C/C++ Source or Header  |  1996-03-13  |  46KB  |  2,014 lines

  1. #ifndef lint
  2. #ifndef NOID
  3. static char    elsieid[] = "@(#)zic.c    7.56";
  4. #endif /* !defined NOID */
  5. #endif /* !defined lint */
  6.  
  7. #include "private.h"
  8. #include "tzfile.h"
  9. #ifdef unix
  10. #include "sys/stat.h"            /* for umask manifest constants */
  11. #endif /* defined unix */
  12.  
  13. /*
  14. ** On some ancient hosts, predicates like `isspace(C)' are defined
  15. ** only if isascii(C) || C == EOF.  Modern hosts obey the C Standard,
  16. ** which says they are defined only if C == ((unsigned char) C) || C == EOF.
  17. ** Neither the C Standard nor Posix require that `isascii' exist.
  18. ** For portability, we check both ancient and modern requirements.
  19. ** If isascii is not defined, the isascii check succeeds trivially.
  20. */
  21. #include "ctype.h"
  22. #ifndef isascii
  23. #define isascii(x) 1
  24. #endif
  25.  
  26. struct rule {
  27.     const char *    r_filename;
  28.     int        r_linenum;
  29.     const char *    r_name;
  30.  
  31.     int        r_loyear;    /* for example, 1986 */
  32.     int        r_hiyear;    /* for example, 1986 */
  33.     const char *    r_yrtype;
  34.  
  35.     int        r_month;    /* 0..11 */
  36.  
  37.     int        r_dycode;    /* see below */
  38.     int        r_dayofmonth;
  39.     int        r_wday;
  40.  
  41.     long        r_tod;        /* time from midnight */
  42.     int        r_todisstd;    /* above is standard time if TRUE */
  43.                     /* or wall clock time if FALSE */
  44.     int        r_todisgmt;    /* above is GMT if TRUE */
  45.                     /* or local time if FALSE */
  46.     long        r_stdoff;    /* offset from standard time */
  47.     const char *    r_abbrvar;    /* variable part of abbreviation */
  48.  
  49.     int        r_todo;        /* a rule to do (used in outzone) */
  50.     time_t        r_temp;        /* used in outzone */
  51. };
  52.  
  53. /*
  54. **    r_dycode        r_dayofmonth    r_wday
  55. */
  56.  
  57. #define DC_DOM        0    /* 1..31 */    /* unused */
  58. #define DC_DOWGEQ    1    /* 1..31 */    /* 0..6 (Sun..Sat) */
  59. #define DC_DOWLEQ    2    /* 1..31 */    /* 0..6 (Sun..Sat) */
  60.  
  61. struct zone {
  62.     const char *    z_filename;
  63.     int        z_linenum;
  64.  
  65.     const char *    z_name;
  66.     long        z_gmtoff;
  67.     const char *    z_rule;
  68.     const char *    z_format;
  69.  
  70.     long        z_stdoff;
  71.  
  72.     struct rule *    z_rules;
  73.     int        z_nrules;
  74.  
  75.     struct rule    z_untilrule;
  76.     time_t        z_untiltime;
  77. };
  78.  
  79. extern int    getopt P((int argc, char * const argv[],
  80.             const char * options));
  81. extern char *    icatalloc P((char * old, const char * new));
  82. extern char *    icpyalloc P((const char * string));
  83. extern void    ifree P((char * p));
  84. extern char *    imalloc P((int n));
  85. extern void *    irealloc P((void * old, int n));
  86. extern int    link P((const char * fromname, const char * toname));
  87. extern char *    optarg;
  88. extern int    optind;
  89. extern char *    scheck P((const char * string, const char * format));
  90.  
  91. static void    addtt P((time_t starttime, int type));
  92. static int    addtype P((long gmtoff, const char * abbr, int isdst,
  93.                 int ttisstd, int ttisgmt));
  94. static void    leapadd P((time_t t, int positive, int rolling, int count));
  95. static void    adjleap P((void));
  96. static void    associate P((void));
  97. static int    ciequal P((const char * ap, const char * bp));
  98. static void    convert P((long val, char * buf));
  99. static void    dolink P((const char * fromfile, const char * tofile));
  100. static void    doabbr P((char * abbr, const char * format,
  101.             const char * letters, int isdst));
  102. static void    eat P((const char * name, int num));
  103. static void    eats P((const char * name, int num,
  104.             const char * rname, int rnum));
  105. static long    eitol P((int i));
  106. static void    error P((const char * message));
  107. static char **    getfields P((char * buf));
  108. static long    gethms P((const char * string, const char * errstrng,
  109.             int signable));
  110. static void    infile P((const char * filename));
  111. static void    inleap P((char ** fields, int nfields));
  112. static void    inlink P((char ** fields, int nfields));
  113. static void    inrule P((char ** fields, int nfields));
  114. static int    inzcont P((char ** fields, int nfields));
  115. static int    inzone P((char ** fields, int nfields));
  116. static int    inzsub P((char ** fields, int nfields, int iscont));
  117. static int    itsabbr P((const char * abbr, const char * word));
  118. static int    itsdir P((const char * name));
  119. static int    lowerit P((int c));
  120. static char *    memcheck P((char * tocheck));
  121. static int    mkdirs P((char * filename));
  122. static void    newabbr P((const char * abbr));
  123. static long    oadd P((long t1, long t2));
  124. static void    outzone P((const struct zone * zp, int ntzones));
  125. static void    puttzcode P((long code, FILE * fp));
  126. static int    rcomp P((const void * leftp, const void * rightp));
  127. static time_t    rpytime P((const struct rule * rp, int wantedy));
  128. static void    rulesub P((struct rule * rp,
  129.             const char * loyearp, const char * hiyearp,
  130.             const char * typep, const char * monthp,
  131.             const char * dayp, const char * timep));
  132. static void    setboundaries P((void));
  133. static time_t    tadd P((time_t t1, long t2));
  134. static void    usage P((void));
  135. static void    writezone P((const char * name));
  136. static int    yearistype P((int year, const char * type));
  137.  
  138. static int        charcnt;
  139. static int        errors;
  140. static const char *    filename;
  141. static int        leapcnt;
  142. static int        linenum;
  143. static time_t        max_time;
  144. static int        max_year;
  145. static time_t        min_time;
  146. static int        min_year;
  147. static int        noise;
  148. static const char *    rfilename;
  149. static int        rlinenum;
  150. static const char *    progname;
  151. static int        timecnt;
  152. static int        typecnt;
  153.  
  154. /*
  155. ** Line codes.
  156. */
  157.  
  158. #define LC_RULE        0
  159. #define LC_ZONE        1
  160. #define LC_LINK        2
  161. #define LC_LEAP        3
  162.  
  163. /*
  164. ** Which fields are which on a Zone line.
  165. */
  166.  
  167. #define ZF_NAME        1
  168. #define ZF_GMTOFF    2
  169. #define ZF_RULE        3
  170. #define ZF_FORMAT    4
  171. #define ZF_TILYEAR    5
  172. #define ZF_TILMONTH    6
  173. #define ZF_TILDAY    7
  174. #define ZF_TILTIME    8
  175. #define ZONE_MINFIELDS    5
  176. #define ZONE_MAXFIELDS    9
  177.  
  178. /*
  179. ** Which fields are which on a Zone continuation line.
  180. */
  181.  
  182. #define ZFC_GMTOFF    0
  183. #define ZFC_RULE    1
  184. #define ZFC_FORMAT    2
  185. #define ZFC_TILYEAR    3
  186. #define ZFC_TILMONTH    4
  187. #define ZFC_TILDAY    5
  188. #define ZFC_TILTIME    6
  189. #define ZONEC_MINFIELDS    3
  190. #define ZONEC_MAXFIELDS    7
  191.  
  192. /*
  193. ** Which files are which on a Rule line.
  194. */
  195.  
  196. #define RF_NAME        1
  197. #define RF_LOYEAR    2
  198. #define RF_HIYEAR    3
  199. #define RF_COMMAND    4
  200. #define RF_MONTH    5
  201. #define RF_DAY        6
  202. #define RF_TOD        7
  203. #define RF_STDOFF    8
  204. #define RF_ABBRVAR    9
  205. #define RULE_FIELDS    10
  206.  
  207. /*
  208. ** Which fields are which on a Link line.
  209. */
  210.  
  211. #define LF_FROM        1
  212. #define LF_TO        2
  213. #define LINK_FIELDS    3
  214.  
  215. /*
  216. ** Which fields are which on a Leap line.
  217. */
  218.  
  219. #define LP_YEAR        1
  220. #define LP_MONTH    2
  221. #define LP_DAY        3
  222. #define LP_TIME        4
  223. #define LP_CORR        5
  224. #define LP_ROLL        6
  225. #define LEAP_FIELDS    7
  226.  
  227. /*
  228. ** Year synonyms.
  229. */
  230.  
  231. #define YR_MINIMUM    0
  232. #define YR_MAXIMUM    1
  233. #define YR_ONLY        2
  234.  
  235. static struct rule *    rules;
  236. static int        nrules;    /* number of rules */
  237.  
  238. static struct zone *    zones;
  239. static int        nzones;    /* number of zones */
  240.  
  241. struct link {
  242.     const char *    l_filename;
  243.     int        l_linenum;
  244.     const char *    l_from;
  245.     const char *    l_to;
  246. };
  247.  
  248. static struct link *    links;
  249. static int        nlinks;
  250.  
  251. struct lookup {
  252.     const char *    l_word;
  253.     const int    l_value;
  254. };
  255.  
  256. static struct lookup const *    byword P((const char * string,
  257.                     const struct lookup * lp));
  258.  
  259. static struct lookup const    line_codes[] = {
  260.     { "Rule",    LC_RULE },
  261.     { "Zone",    LC_ZONE },
  262.     { "Link",    LC_LINK },
  263.     { "Leap",    LC_LEAP },
  264.     { NULL,        0}
  265. };
  266.  
  267. static struct lookup const    mon_names[] = {
  268.     { "January",    TM_JANUARY },
  269.     { "February",    TM_FEBRUARY },
  270.     { "March",    TM_MARCH },
  271.     { "April",    TM_APRIL },
  272.     { "May",    TM_MAY },
  273.     { "June",    TM_JUNE },
  274.     { "July",    TM_JULY },
  275.     { "August",    TM_AUGUST },
  276.     { "September",    TM_SEPTEMBER },
  277.     { "October",    TM_OCTOBER },
  278.     { "November",    TM_NOVEMBER },
  279.     { "December",    TM_DECEMBER },
  280.     { NULL,        0 }
  281. };
  282.  
  283. static struct lookup const    wday_names[] = {
  284.     { "Sunday",    TM_SUNDAY },
  285.     { "Monday",    TM_MONDAY },
  286.     { "Tuesday",    TM_TUESDAY },
  287.     { "Wednesday",    TM_WEDNESDAY },
  288.     { "Thursday",    TM_THURSDAY },
  289.     { "Friday",    TM_FRIDAY },
  290.     { "Saturday",    TM_SATURDAY },
  291.     { NULL,        0 }
  292. };
  293.  
  294. static struct lookup const    lasts[] = {
  295.     { "last-Sunday",    TM_SUNDAY },
  296.     { "last-Monday",    TM_MONDAY },
  297.     { "last-Tuesday",    TM_TUESDAY },
  298.     { "last-Wednesday",    TM_WEDNESDAY },
  299.     { "last-Thursday",    TM_THURSDAY },
  300.     { "last-Friday",    TM_FRIDAY },
  301.     { "last-Saturday",    TM_SATURDAY },
  302.     { NULL,            0 }
  303. };
  304.  
  305. static struct lookup const    begin_years[] = {
  306.     { "minimum",    YR_MINIMUM },
  307.     { "maximum",    YR_MAXIMUM },
  308.     { NULL,        0 }
  309. };
  310.  
  311. static struct lookup const    end_years[] = {
  312.     { "minimum",    YR_MINIMUM },
  313.     { "maximum",    YR_MAXIMUM },
  314.     { "only",    YR_ONLY },
  315.     { NULL,        0 }
  316. };
  317.  
  318. static struct lookup const    leap_types[] = {
  319.     { "Rolling",    TRUE },
  320.     { "Stationary",    FALSE },
  321.     { NULL,        0 }
  322. };
  323.  
  324. static const int    len_months[2][MONSPERYEAR] = {
  325.     { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
  326.     { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
  327. };
  328.  
  329. static const int    len_years[2] = {
  330.     DAYSPERNYEAR, DAYSPERLYEAR
  331. };
  332.  
  333. static time_t        ats[TZ_MAX_TIMES];
  334. static unsigned char    types[TZ_MAX_TIMES];
  335. static long        gmtoffs[TZ_MAX_TYPES];
  336. static char        isdsts[TZ_MAX_TYPES];
  337. static unsigned char    abbrinds[TZ_MAX_TYPES];
  338. static char        ttisstds[TZ_MAX_TYPES];
  339. static char        ttisgmts[TZ_MAX_TYPES];
  340. static char        chars[TZ_MAX_CHARS];
  341. static time_t        trans[TZ_MAX_LEAPS];
  342. static long        corr[TZ_MAX_LEAPS];
  343. static char        roll[TZ_MAX_LEAPS];
  344.  
  345. /*
  346. ** Memory allocation.
  347. */
  348.  
  349. static char *
  350. memcheck(ptr)
  351. char * const    ptr;
  352. {
  353.     if (ptr == NULL) {
  354.         (void) perror(progname);
  355.         (void) exit(EXIT_FAILURE);
  356.     }
  357.     return ptr;
  358. }
  359.  
  360. #define emalloc(size)        memcheck(imalloc(size))
  361. #define erealloc(ptr, size)    memcheck(irealloc((ptr), (size)))
  362. #define ecpyalloc(ptr)        memcheck(icpyalloc(ptr))
  363. #define ecatalloc(oldp, newp)    memcheck(icatalloc((oldp), (newp)))
  364.  
  365. /*
  366. ** Error handling.
  367. */
  368.  
  369. static void
  370. eats(name, num, rname, rnum)
  371. const char * const    name;
  372. const int        num;
  373. const char * const    rname;
  374. const int        rnum;
  375. {
  376.     filename = name;
  377.     linenum = num;
  378.     rfilename = rname;
  379.     rlinenum = rnum;
  380. }
  381.  
  382. static void
  383. eat(name, num)
  384. const char * const    name;
  385. const int        num;
  386. {
  387.     eats(name, num, (char *) NULL, -1);
  388. }
  389.  
  390. static void
  391. error(string)
  392. const char * const    string;
  393. {
  394.     /*
  395.     ** Match the format of "cc" to allow sh users to
  396.     **    zic ... 2>&1 | error -t "*" -v
  397.     ** on BSD systems.
  398.     */
  399.     (void) fprintf(stderr, "\"%s\", line %d: %s",
  400.         filename, linenum, string);
  401.     if (rfilename != NULL)
  402.         (void) fprintf(stderr, " (rule from \"%s\", line %d)",
  403.             rfilename, rlinenum);
  404.     (void) fprintf(stderr, "\n");
  405.     ++errors;
  406. }
  407.  
  408. static void
  409. usage P((void))
  410. {
  411.     (void) fprintf(stderr, "%s: usage is %s \
  412. [ -s ] [ -v ] [ -l localtime ] [ -p posixrules ] [ -d directory ]\n\
  413. \t[ -L leapseconds ] [ -y yearistype ] [ filename ... ]\n",
  414.         progname, progname);
  415.     (void) exit(EXIT_FAILURE);
  416. }
  417.  
  418. static const char *    psxrules;
  419. static const char *    lcltime;
  420. static const char *    directory;
  421. static const char *    leapsec;
  422. static const char *    yitcommand;
  423. static int        sflag = FALSE;
  424.  
  425. int
  426. main(argc, argv)
  427. int    argc;
  428. char *    argv[];
  429. {
  430.     register int    i;
  431.     register int    j;
  432.     register int    c;
  433.  
  434. #ifdef unix
  435.     (void) umask(umask(S_IWGRP | S_IWOTH) | (S_IWGRP | S_IWOTH));
  436. #endif /* defined unix */
  437.     progname = argv[0];
  438.     while ((c = getopt(argc, argv, "d:l:p:L:vsy:")) != EOF)
  439.         switch (c) {
  440.             default:
  441.                 usage();
  442.             case 'd':
  443.                 if (directory == NULL)
  444.                     directory = optarg;
  445.                 else {
  446.                     (void) fprintf(stderr,
  447. "%s: More than one -d option specified\n",
  448.                         progname);
  449.                     (void) exit(EXIT_FAILURE);
  450.                 }
  451.                 break;
  452.             case 'l':
  453.                 if (lcltime == NULL)
  454.                     lcltime = optarg;
  455.                 else {
  456.                     (void) fprintf(stderr,
  457. "%s: More than one -l option specified\n",
  458.                         progname);
  459.                     (void) exit(EXIT_FAILURE);
  460.                 }
  461.                 break;
  462.             case 'p':
  463.                 if (psxrules == NULL)
  464.                     psxrules = optarg;
  465.                 else {
  466.                     (void) fprintf(stderr,
  467. "%s: More than one -p option specified\n",
  468.                         progname);
  469.                     (void) exit(EXIT_FAILURE);
  470.                 }
  471.                 break;
  472.             case 'y':
  473.                 if (yitcommand == NULL)
  474.                     yitcommand = optarg;
  475.                 else {
  476.                     (void) fprintf(stderr,
  477. "%s: More than one -y option specified\n",
  478.                         progname);
  479.                     (void) exit(EXIT_FAILURE);
  480.                 }
  481.                 break;
  482.             case 'L':
  483.                 if (leapsec == NULL)
  484.                     leapsec = optarg;
  485.                 else {
  486.                     (void) fprintf(stderr,
  487. "%s: More than one -L option specified\n",
  488.                         progname);
  489.                     (void) exit(EXIT_FAILURE);
  490.                 }
  491.                 break;
  492.             case 'v':
  493.                 noise = TRUE;
  494.                 break;
  495.             case 's':
  496.                 sflag = TRUE;
  497.                 break;
  498.         }
  499.     if (optind == argc - 1 && strcmp(argv[optind], "=") == 0)
  500.         usage();    /* usage message by request */
  501.     if (directory == NULL)
  502.         directory = TZDIR;
  503.     if (yitcommand == NULL)
  504.         yitcommand = "yearistype";
  505.  
  506.     setboundaries();
  507.  
  508.     if (optind < argc && leapsec != NULL) {
  509.         infile(leapsec);
  510.         adjleap();
  511.     }
  512.  
  513.     for (i = optind; i < argc; ++i)
  514.         infile(argv[i]);
  515.     if (errors)
  516.         (void) exit(EXIT_FAILURE);
  517.     associate();
  518.     for (i = 0; i < nzones; i = j) {
  519.         /*
  520.         ** Find the next non-continuation zone entry.
  521.         */
  522.         for (j = i + 1; j < nzones && zones[j].z_name == NULL; ++j)
  523.             continue;
  524.         outzone(&zones[i], j - i);
  525.     }
  526.     /*
  527.     ** Make links.
  528.     */
  529.     for (i = 0; i < nlinks; ++i)
  530.         dolink(links[i].l_from, links[i].l_to);
  531.     if (lcltime != NULL)
  532.         dolink(lcltime, TZDEFAULT);
  533.     if (psxrules != NULL)
  534.         dolink(psxrules, TZDEFRULES);
  535.     return (errors == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
  536. }
  537.  
  538. static void
  539. dolink(fromfile, tofile)
  540. const char * const    fromfile;
  541. const char * const    tofile;
  542. {
  543.     register char *    fromname;
  544.     register char *    toname;
  545.  
  546.     if (fromfile[0] == '/')
  547.         fromname = ecpyalloc(fromfile);
  548.     else {
  549.         fromname = ecpyalloc(directory);
  550.         fromname = ecatalloc(fromname, "/");
  551.         fromname = ecatalloc(fromname, fromfile);
  552.     }
  553.     if (tofile[0] == '/')
  554.         toname = ecpyalloc(tofile);
  555.     else {
  556.         toname = ecpyalloc(directory);
  557.         toname = ecatalloc(toname, "/");
  558.         toname = ecatalloc(toname, tofile);
  559.     }
  560.     /*
  561.     ** We get to be careful here since
  562.     ** there's a fair chance of root running us.
  563.     */
  564.     if (!itsdir(toname))
  565.         (void) remove(toname);
  566.     if (link(fromname, toname) != 0) {
  567.         if (mkdirs(toname) != 0)
  568.             (void) exit(EXIT_FAILURE);
  569.         if (link(fromname, toname) != 0) {
  570.             (void) fprintf(stderr, "%s: Can't link from %s to ",
  571.                 progname, fromname);
  572.             (void) perror(toname);
  573.             (void) exit(EXIT_FAILURE);
  574.         }
  575.     }
  576.     ifree(fromname);
  577.     ifree(toname);
  578. }
  579.  
  580. #ifndef INT_MIN
  581. #define INT_MIN (~0 << (sizeof (int) * CHAR_BIT - 1))
  582. #endif
  583. #ifndef INT_MAX
  584. #define INT_MAX (~0 - INT_MIN)
  585. #endif
  586.  
  587. #define TIME_T_SIGNED ((time_t) -1 < 0)
  588. #define TIME_T_BIT (sizeof (time_t) * CHAR_BIT)
  589.  
  590. /*
  591. ** The tz file format currently allows at most 32-bit quantities.
  592. ** This restriction should be removed before signed 32-bit values
  593. ** wrap around in 2038, but unfortunately this will require a
  594. ** change to the tz file format.
  595. */
  596.  
  597. #define MAX_BITS_IN_FILE    32
  598. #define TIME_T_BITS_IN_FILE    ((TIME_T_BIT < MAX_BITS_IN_FILE) ? \
  599.                     TIME_T_BIT : MAX_BITS_IN_FILE)
  600.  
  601. static void
  602. setboundaries P((void))
  603. {
  604.     if (TIME_T_SIGNED) {
  605.         min_time = ~ (time_t) 0;
  606.         min_time <<= TIME_T_BITS_IN_FILE - 1;
  607.         max_time = ~ (time_t) 0 - min_time;
  608.         if (sflag)
  609.             min_time = 0;
  610.     } else {
  611.         min_time = 0;
  612.         max_time = 2 - sflag;
  613.         max_time <<= TIME_T_BITS_IN_FILE - 1;
  614.         --max_time;
  615.     }
  616.     min_year = TM_YEAR_BASE + gmtime(&min_time)->tm_year;
  617.     max_year = TM_YEAR_BASE + gmtime(&max_time)->tm_year;
  618. }
  619.  
  620. static int
  621. itsdir(name)
  622. const char * const    name;
  623. {
  624.     register char *    myname;
  625.     register int    accres;
  626.  
  627.     myname = ecpyalloc(name);
  628.     myname = ecatalloc(myname, "/.");
  629.     accres = access(myname, F_OK);
  630.     ifree(myname);
  631.     return accres == 0;
  632. }
  633.  
  634. /*
  635. ** Associate sets of rules with zones.
  636. */
  637.  
  638. /*
  639. ** Sort by rule name.
  640. */
  641.  
  642. static int
  643. rcomp(cp1, cp2)
  644. const void *    cp1;
  645. const void *    cp2;
  646. {
  647.     return strcmp(((const struct rule *) cp1)->r_name,
  648.         ((const struct rule *) cp2)->r_name);
  649. }
  650.  
  651. static void
  652. associate P((void))
  653. {
  654.     register struct zone *    zp;
  655.     register struct rule *    rp;
  656.     register int        base, out;
  657.     register int        i;
  658.  
  659.     if (nrules != 0)
  660.         (void) qsort((void *) rules, (size_t) nrules,
  661.             (size_t) sizeof *rules, rcomp);
  662.     for (i = 0; i < nzones; ++i) {
  663.         zp = &zones[i];
  664.         zp->z_rules = NULL;
  665.         zp->z_nrules = 0;
  666.     }
  667.     for (base = 0; base < nrules; base = out) {
  668.         rp = &rules[base];
  669.         for (out = base + 1; out < nrules; ++out)
  670.             if (strcmp(rp->r_name, rules[out].r_name) != 0)
  671.                 break;
  672.         for (i = 0; i < nzones; ++i) {
  673.             zp = &zones[i];
  674.             if (strcmp(zp->z_rule, rp->r_name) != 0)
  675.                 continue;
  676.             zp->z_rules = rp;
  677.             zp->z_nrules = out - base;
  678.         }
  679.     }
  680.     for (i = 0; i < nzones; ++i) {
  681.         zp = &zones[i];
  682.         if (zp->z_nrules == 0) {
  683.             /*
  684.             ** Maybe we have a local standard time offset.
  685.             */
  686.             eat(zp->z_filename, zp->z_linenum);
  687.             zp->z_stdoff = gethms(zp->z_rule, "unruly zone", TRUE);
  688.             /*
  689.             ** Note, though, that if there's no rule,
  690.             ** a '%s' in the format is a bad thing.
  691.             */
  692.             if (strchr(zp->z_format, '%') != 0)
  693.                 error("%s in ruleless zone");
  694.         }
  695.     }
  696.     if (errors)
  697.         (void) exit(EXIT_FAILURE);
  698. }
  699.  
  700. static void
  701. infile(name)
  702. const char *    name;
  703. {
  704.     register FILE *            fp;
  705.     register char **        fields;
  706.     register char *            cp;
  707.     register const struct lookup *    lp;
  708.     register int            nfields;
  709.     register int            wantcont;
  710.     register int            num;
  711.     char                buf[BUFSIZ];
  712.  
  713.     if (strcmp(name, "-") == 0) {
  714.         name = "standard input";
  715.         fp = stdin;
  716.     } else if ((fp = fopen(name, "r")) == NULL) {
  717.         (void) fprintf(stderr, "%s: Can't open ", progname);
  718.         (void) perror(name);
  719.         (void) exit(EXIT_FAILURE);
  720.     }
  721.     wantcont = FALSE;
  722.     for (num = 1; ; ++num) {
  723.         eat(name, num);
  724.         if (fgets(buf, (int) sizeof buf, fp) != buf)
  725.             break;
  726.         cp = strchr(buf, '\n');
  727.         if (cp == NULL) {
  728.             error("line too long");
  729.             (void) exit(EXIT_FAILURE);
  730.         }
  731.         *cp = '\0';
  732.         fields = getfields(buf);
  733.         nfields = 0;
  734.         while (fields[nfields] != NULL) {
  735.             static char    nada;
  736.  
  737.             if (strcmp(fields[nfields], "-") == 0)
  738.                 fields[nfields] = &nada;
  739.             ++nfields;
  740.         }
  741.         if (nfields == 0) {
  742.             /* nothing to do */
  743.         } else if (wantcont) {
  744.             wantcont = inzcont(fields, nfields);
  745.         } else {
  746.             lp = byword(fields[0], line_codes);
  747.             if (lp == NULL)
  748.                 error("input line of unknown type");
  749.             else switch ((int) (lp->l_value)) {
  750.                 case LC_RULE:
  751.                     inrule(fields, nfields);
  752.                     wantcont = FALSE;
  753.                     break;
  754.                 case LC_ZONE:
  755.                     wantcont = inzone(fields, nfields);
  756.                     break;
  757.                 case LC_LINK:
  758.                     inlink(fields, nfields);
  759.                     wantcont = FALSE;
  760.                     break;
  761.                 case LC_LEAP:
  762.                     if (name != leapsec)
  763.                         (void) fprintf(stderr,
  764. "%s: Leap line in non leap seconds file %s\n",
  765.                             progname, name);
  766.                     else    inleap(fields, nfields);
  767.                     wantcont = FALSE;
  768.                     break;
  769.                 default:    /* "cannot happen" */
  770.                     (void) fprintf(stderr,
  771. "%s: panic: Invalid l_value %d\n",
  772.                         progname, lp->l_value);
  773.                     (void) exit(EXIT_FAILURE);
  774.             }
  775.         }
  776.         ifree((char *) fields);
  777.     }
  778.     if (ferror(fp)) {
  779.         (void) fprintf(stderr, "%s: Error reading ", progname);
  780.         (void) perror(filename);
  781.         (void) exit(EXIT_FAILURE);
  782.     }
  783.     if (fp != stdin && fclose(fp)) {
  784.         (void) fprintf(stderr, "%s: Error closing ", progname);
  785.         (void) perror(filename);
  786.         (void) exit(EXIT_FAILURE);
  787.     }
  788.     if (wantcont)
  789.         error("expected continuation line not found");
  790. }
  791.  
  792. /*
  793. ** Convert a string of one of the forms
  794. **    h    -h    hh:mm    -hh:mm    hh:mm:ss    -hh:mm:ss
  795. ** into a number of seconds.
  796. ** A null string maps to zero.
  797. ** Call error with errstring and return zero on errors.
  798. */
  799.  
  800. static long
  801. gethms(string, errstring, signable)
  802. const char *        string;
  803. const char * const    errstring;
  804. const int        signable;
  805. {
  806.     int    hh, mm, ss, sign;
  807.  
  808.     if (string == NULL || *string == '\0')
  809.         return 0;
  810.     if (!signable)
  811.         sign = 1;
  812.     else if (*string == '-') {
  813.         sign = -1;
  814.         ++string;
  815.     } else    sign = 1;
  816.     if (sscanf(string, scheck(string, "%d"), &hh) == 1)
  817.         mm = ss = 0;
  818.     else if (sscanf(string, scheck(string, "%d:%d"), &hh, &mm) == 2)
  819.         ss = 0;
  820.     else if (sscanf(string, scheck(string, "%d:%d:%d"),
  821.         &hh, &mm, &ss) != 3) {
  822.             error(errstring);
  823.             return 0;
  824.     }
  825.     if (hh < 0 || hh >= HOURSPERDAY ||
  826.         mm < 0 || mm >= MINSPERHOUR ||
  827.         ss < 0 || ss > SECSPERMIN) {
  828.             error(errstring);
  829.             return 0;
  830.     }
  831.     return eitol(sign) *
  832.         (eitol(hh * MINSPERHOUR + mm) *
  833.         eitol(SECSPERMIN) + eitol(ss));
  834. }
  835.  
  836. static void
  837. inrule(fields, nfields)
  838. register char ** const    fields;
  839. const int        nfields;
  840. {
  841.     static struct rule    r;
  842.  
  843.     if (nfields != RULE_FIELDS) {
  844.         error("wrong number of fields on Rule line");
  845.         return;
  846.     }
  847.     if (*fields[RF_NAME] == '\0') {
  848.         error("nameless rule");
  849.         return;
  850.     }
  851.     r.r_filename = filename;
  852.     r.r_linenum = linenum;
  853.     r.r_stdoff = gethms(fields[RF_STDOFF], "invalid saved time", TRUE);
  854.     rulesub(&r, fields[RF_LOYEAR], fields[RF_HIYEAR], fields[RF_COMMAND],
  855.         fields[RF_MONTH], fields[RF_DAY], fields[RF_TOD]);
  856.     r.r_name = ecpyalloc(fields[RF_NAME]);
  857.     r.r_abbrvar = ecpyalloc(fields[RF_ABBRVAR]);
  858.     rules = (struct rule *) (void *) erealloc((char *) rules,
  859.         (int) ((nrules + 1) * sizeof *rules));
  860.     rules[nrules++] = r;
  861. }
  862.  
  863. static int
  864. inzone(fields, nfields)
  865. register char ** const    fields;
  866. const int        nfields;
  867. {
  868.     register int    i;
  869.     static char *    buf;
  870.  
  871.     if (nfields < ZONE_MINFIELDS || nfields > ZONE_MAXFIELDS) {
  872.         error("wrong number of fields on Zone line");
  873.         return FALSE;
  874.     }
  875.     if (strcmp(fields[ZF_NAME], TZDEFAULT) == 0 && lcltime != NULL) {
  876.         buf = erealloc(buf, (int) (132 + strlen(TZDEFAULT)));
  877.         (void) sprintf(buf,
  878. "\"Zone %s\" line and -l option are mutually exclusive",
  879.             TZDEFAULT);
  880.         error(buf);
  881.         return FALSE;
  882.     }
  883.     if (strcmp(fields[ZF_NAME], TZDEFRULES) == 0 && psxrules != NULL) {
  884.         buf = erealloc(buf, (int) (132 + strlen(TZDEFRULES)));
  885.         (void) sprintf(buf,
  886. "\"Zone %s\" line and -p option are mutually exclusive",
  887.             TZDEFRULES);
  888.         error(buf);
  889.         return FALSE;
  890.     }
  891.     for (i = 0; i < nzones; ++i)
  892.         if (zones[i].z_name != NULL &&
  893.             strcmp(zones[i].z_name, fields[ZF_NAME]) == 0) {
  894.                 buf = erealloc(buf, (int) (132 +
  895.                     strlen(fields[ZF_NAME]) +
  896.                     strlen(zones[i].z_filename)));
  897.                 (void) sprintf(buf,
  898. "duplicate zone name %s (file \"%s\", line %d)",
  899.                     fields[ZF_NAME],
  900.                     zones[i].z_filename,
  901.                     zones[i].z_linenum);
  902.                 error(buf);
  903.                 return FALSE;
  904.         }
  905.     return inzsub(fields, nfields, FALSE);
  906. }
  907.  
  908. static int
  909. inzcont(fields, nfields)
  910. register char ** const    fields;
  911. const int        nfields;
  912. {
  913.     if (nfields < ZONEC_MINFIELDS || nfields > ZONEC_MAXFIELDS) {
  914.         error("wrong number of fields on Zone continuation line");
  915.         return FALSE;
  916.     }
  917.     return inzsub(fields, nfields, TRUE);
  918. }
  919.  
  920. static int
  921. inzsub(fields, nfields, iscont)
  922. register char ** const    fields;
  923. const int        nfields;
  924. const int        iscont;
  925. {
  926.     register char *        cp;
  927.     static struct zone    z;
  928.     register int        i_gmtoff, i_rule, i_format;
  929.     register int        i_untilyear, i_untilmonth;
  930.     register int        i_untilday, i_untiltime;
  931.     register int        hasuntil;
  932.  
  933.     if (iscont) {
  934.         i_gmtoff = ZFC_GMTOFF;
  935.         i_rule = ZFC_RULE;
  936.         i_format = ZFC_FORMAT;
  937.         i_untilyear = ZFC_TILYEAR;
  938.         i_untilmonth = ZFC_TILMONTH;
  939.         i_untilday = ZFC_TILDAY;
  940.         i_untiltime = ZFC_TILTIME;
  941.         z.z_name = NULL;
  942.     } else {
  943.         i_gmtoff = ZF_GMTOFF;
  944.         i_rule = ZF_RULE;
  945.         i_format = ZF_FORMAT;
  946.         i_untilyear = ZF_TILYEAR;
  947.         i_untilmonth = ZF_TILMONTH;
  948.         i_untilday = ZF_TILDAY;
  949.         i_untiltime = ZF_TILTIME;
  950.         z.z_name = ecpyalloc(fields[ZF_NAME]);
  951.     }
  952.     z.z_filename = filename;
  953.     z.z_linenum = linenum;
  954.     z.z_gmtoff = gethms(fields[i_gmtoff], "invalid GMT offset", TRUE);
  955.     if ((cp = strchr(fields[i_format], '%')) != 0) {
  956.         if (*++cp != 's' || strchr(cp, '%') != 0) {
  957.             error("invalid abbreviation format");
  958.             return FALSE;
  959.         }
  960.     }
  961.     z.z_rule = ecpyalloc(fields[i_rule]);
  962.     z.z_format = ecpyalloc(fields[i_format]);
  963.     hasuntil = nfields > i_untilyear;
  964.     if (hasuntil) {
  965.         z.z_untilrule.r_filename = filename;
  966.         z.z_untilrule.r_linenum = linenum;
  967.         rulesub(&z.z_untilrule,
  968.             fields[i_untilyear],
  969.             "only",
  970.             "",
  971.             (nfields > i_untilmonth) ?
  972.             fields[i_untilmonth] : "Jan",
  973.             (nfields > i_untilday) ? fields[i_untilday] : "1",
  974.             (nfields > i_untiltime) ? fields[i_untiltime] : "0");
  975.         z.z_untiltime = rpytime(&z.z_untilrule,
  976.             z.z_untilrule.r_loyear);
  977.         if (iscont && nzones > 0 &&
  978.             z.z_untiltime > min_time &&
  979.             z.z_untiltime < max_time &&
  980.             zones[nzones - 1].z_untiltime > min_time &&
  981.             zones[nzones - 1].z_untiltime < max_time &&
  982.             zones[nzones - 1].z_untiltime >= z.z_untiltime) {
  983.                 error("Zone continuation line end time is not \
  984. after end time of previous line");
  985.                 return FALSE;
  986.         }
  987.     }
  988.     zones = (struct zone *) (void *) erealloc((char *) zones,
  989.         (int) ((nzones + 1) * sizeof *zones));
  990.     zones[nzones++] = z;
  991.     /*
  992.     ** If there was an UNTIL field on this line,
  993.     ** there's more information about the zone on the next line.
  994.     */
  995.     return hasuntil;
  996. }
  997.  
  998. static void
  999. inleap(fields, nfields)
  1000. register char ** const    fields;
  1001. const int        nfields;
  1002. {
  1003.     register const char *        cp;
  1004.     register const struct lookup *    lp;
  1005.     register int            i, j;
  1006.     int                year, month, day;
  1007.     long                dayoff, tod;
  1008.     time_t                t;
  1009.  
  1010.     if (nfields != LEAP_FIELDS) {
  1011.         error("wrong number of fields on Leap line");
  1012.         return;
  1013.     }
  1014.     dayoff = 0;
  1015.     cp = fields[LP_YEAR];
  1016.     if (sscanf(cp, scheck(cp, "%d"), &year) != 1) {
  1017.             /*
  1018.              * Leapin' Lizards!
  1019.              */
  1020.             error("invalid leaping year");
  1021.             return;
  1022.     }
  1023.     j = EPOCH_YEAR;
  1024.     while (j != year) {
  1025.         if (year > j) {
  1026.             i = len_years[isleap(j)];
  1027.             ++j;
  1028.         } else {
  1029.             --j;
  1030.             i = -len_years[isleap(j)];
  1031.         }
  1032.         dayoff = oadd(dayoff, eitol(i));
  1033.     }
  1034.     if ((lp = byword(fields[LP_MONTH], mon_names)) == NULL) {
  1035.         error("invalid month name");
  1036.         return;
  1037.     }
  1038.     month = lp->l_value;
  1039.     j = TM_JANUARY;
  1040.     while (j != month) {
  1041.         i = len_months[isleap(year)][j];
  1042.         dayoff = oadd(dayoff, eitol(i));
  1043.         ++j;
  1044.     }
  1045.     cp = fields[LP_DAY];
  1046.     if (sscanf(cp, scheck(cp, "%d"), &day) != 1 ||
  1047.         day <= 0 || day > len_months[isleap(year)][month]) {
  1048.             error("invalid day of month");
  1049.             return;
  1050.     }
  1051.     dayoff = oadd(dayoff, eitol(day - 1));
  1052.     if (dayoff < 0 && !TIME_T_SIGNED) {
  1053.         error("time before zero");
  1054.         return;
  1055.     }
  1056.     t = (time_t) dayoff * SECSPERDAY;
  1057.     /*
  1058.     ** Cheap overflow check.
  1059.     */
  1060.     if (t / SECSPERDAY != dayoff) {
  1061.         error("time overflow");
  1062.         return;
  1063.     }
  1064.     tod = gethms(fields[LP_TIME], "invalid time of day", FALSE);
  1065.     cp = fields[LP_CORR];
  1066.     {
  1067.         register int    positive;
  1068.         int        count;
  1069.  
  1070.         if (strcmp(cp, "") == 0) { /* infile() turns "-" into "" */
  1071.             positive = FALSE;
  1072.             count = 1;
  1073.         } else if (strcmp(cp, "--") == 0) {
  1074.             positive = FALSE;
  1075.             count = 2;
  1076.         } else if (strcmp(cp, "+") == 0) {
  1077.             positive = TRUE;
  1078.             count = 1;
  1079.         } else if (strcmp(cp, "++") == 0) {
  1080.             positive = TRUE;
  1081.             count = 2;
  1082.         } else {
  1083.             error("illegal CORRECTION field on Leap line");
  1084.             return;
  1085.         }
  1086.         if ((lp = byword(fields[LP_ROLL], leap_types)) == NULL) {
  1087.             error("illegal Rolling/Stationary field on Leap line");
  1088.             return;
  1089.         }
  1090.         leapadd(tadd(t, tod), positive, lp->l_value, count);
  1091.     }
  1092. }
  1093.  
  1094. static void
  1095. inlink(fields, nfields)
  1096. register char ** const    fields;
  1097. const int        nfields;
  1098. {
  1099.     struct link    l;
  1100.  
  1101.     if (nfields != LINK_FIELDS) {
  1102.         error("wrong number of fields on Link line");
  1103.         return;
  1104.     }
  1105.     if (*fields[LF_FROM] == '\0') {
  1106.         error("blank FROM field on Link line");
  1107.         return;
  1108.     }
  1109.     if (*fields[LF_TO] == '\0') {
  1110.         error("blank TO field on Link line");
  1111.         return;
  1112.     }
  1113.     l.l_filename = filename;
  1114.     l.l_linenum = linenum;
  1115.     l.l_from = ecpyalloc(fields[LF_FROM]);
  1116.     l.l_to = ecpyalloc(fields[LF_TO]);
  1117.     links = (struct link *) (void *) erealloc((char *) links,
  1118.         (int) ((nlinks + 1) * sizeof *links));
  1119.     links[nlinks++] = l;
  1120. }
  1121.  
  1122. static void
  1123. rulesub(rp, loyearp, hiyearp, typep, monthp, dayp, timep)
  1124. register struct rule * const    rp;
  1125. const char * const        loyearp;
  1126. const char * const        hiyearp;
  1127. const char * const        typep;
  1128. const char * const        monthp;
  1129. const char * const        dayp;
  1130. const char * const        timep;
  1131. {
  1132.     register const struct lookup *    lp;
  1133.     register const char *        cp;
  1134.     register char *            dp;
  1135.     register char *            ep;
  1136.  
  1137.     if ((lp = byword(monthp, mon_names)) == NULL) {
  1138.         error("invalid month name");
  1139.         return;
  1140.     }
  1141.     rp->r_month = lp->l_value;
  1142.     rp->r_todisstd = FALSE;
  1143.     rp->r_todisgmt = FALSE;
  1144.     dp = ecpyalloc(timep);
  1145.     if (*dp != '\0') {
  1146.         ep = dp + strlen(dp) - 1;
  1147.         switch (lowerit(*ep)) {
  1148.             case 's':    /* Standard */
  1149.                 rp->r_todisstd = TRUE;
  1150.                 rp->r_todisgmt = FALSE;
  1151.                 *ep = '\0';
  1152.                 break;
  1153.             case 'w':    /* Wall */
  1154.                 rp->r_todisstd = FALSE;
  1155.                 rp->r_todisgmt = FALSE;
  1156.                 *ep = '\0';
  1157.             case 'g':    /* Greenwich */
  1158.             case 'u':    /* Universal */
  1159.             case 'z':    /* Zulu */
  1160.                 rp->r_todisstd = TRUE;
  1161.                 rp->r_todisgmt = TRUE;
  1162.                 *ep = '\0';
  1163.                 break;
  1164.         }
  1165.     }
  1166.     rp->r_tod = gethms(dp, "invalid time of day", FALSE);
  1167.     ifree(dp);
  1168.     /*
  1169.     ** Year work.
  1170.     */
  1171.     cp = loyearp;
  1172.     lp = byword(cp, begin_years);
  1173.     if (lp != NULL) switch ((int) lp->l_value) {
  1174.         case YR_MINIMUM:
  1175.             rp->r_loyear = INT_MIN;
  1176.             break;
  1177.         case YR_MAXIMUM:
  1178.             rp->r_loyear = INT_MAX;
  1179.             break;
  1180.         default:    /* "cannot happen" */
  1181.             (void) fprintf(stderr,
  1182.                 "%s: panic: Invalid l_value %d\n",
  1183.                 progname, lp->l_value);
  1184.             (void) exit(EXIT_FAILURE);
  1185.     } else if (sscanf(cp, scheck(cp, "%d"), &rp->r_loyear) != 1) {
  1186.         error("invalid starting year");
  1187.         return;
  1188.     }
  1189.     cp = hiyearp;
  1190.     if ((lp = byword(cp, end_years)) != NULL) switch ((int) lp->l_value) {
  1191.         case YR_MINIMUM:
  1192.             rp->r_hiyear = INT_MIN;
  1193.             break;
  1194.         case YR_MAXIMUM:
  1195.             rp->r_hiyear = INT_MAX;
  1196.             break;
  1197.         case YR_ONLY:
  1198.             rp->r_hiyear = rp->r_loyear;
  1199.             break;
  1200.         default:    /* "cannot happen" */
  1201.             (void) fprintf(stderr,
  1202.                 "%s: panic: Invalid l_value %d\n",
  1203.                 progname, lp->l_value);
  1204.             (void) exit(EXIT_FAILURE);
  1205.     } else if (sscanf(cp, scheck(cp, "%d"), &rp->r_hiyear) != 1) {
  1206.         error("invalid ending year");
  1207.         return;
  1208.     }
  1209.     if (rp->r_loyear > rp->r_hiyear) {
  1210.         error("starting year greater than ending year");
  1211.         return;
  1212.     }
  1213.     if (*typep == '\0')
  1214.         rp->r_yrtype = NULL;
  1215.     else {
  1216.         if (rp->r_loyear == rp->r_hiyear) {
  1217.             error("typed single year");
  1218.             return;
  1219.         }
  1220.         rp->r_yrtype = ecpyalloc(typep);
  1221.     }
  1222.     /*
  1223.     ** Day work.
  1224.     ** Accept things such as:
  1225.     **    1
  1226.     **    last-Sunday
  1227.     **    Sun<=20
  1228.     **    Sun>=7
  1229.     */
  1230.     dp = ecpyalloc(dayp);
  1231.     if ((lp = byword(dp, lasts)) != NULL) {
  1232.         rp->r_dycode = DC_DOWLEQ;
  1233.         rp->r_wday = lp->l_value;
  1234.         rp->r_dayofmonth = len_months[1][rp->r_month];
  1235.     } else {
  1236.         if ((ep = strchr(dp, '<')) != 0)
  1237.             rp->r_dycode = DC_DOWLEQ;
  1238.         else if ((ep = strchr(dp, '>')) != 0)
  1239.             rp->r_dycode = DC_DOWGEQ;
  1240.         else {
  1241.             ep = dp;
  1242.             rp->r_dycode = DC_DOM;
  1243.         }
  1244.         if (rp->r_dycode != DC_DOM) {
  1245.             *ep++ = 0;
  1246.             if (*ep++ != '=') {
  1247.                 error("invalid day of month");
  1248.                 ifree(dp);
  1249.                 return;
  1250.             }
  1251.             if ((lp = byword(dp, wday_names)) == NULL) {
  1252.                 error("invalid weekday name");
  1253.                 ifree(dp);
  1254.                 return;
  1255.             }
  1256.             rp->r_wday = lp->l_value;
  1257.         }
  1258.         if (sscanf(ep, scheck(ep, "%d"), &rp->r_dayofmonth) != 1 ||
  1259.             rp->r_dayofmonth <= 0 ||
  1260.             (rp->r_dayofmonth > len_months[1][rp->r_month])) {
  1261.                 error("invalid day of month");
  1262.                 ifree(dp);
  1263.                 return;
  1264.         }
  1265.     }
  1266.     ifree(dp);
  1267. }
  1268.  
  1269. static void
  1270. convert(val, buf)
  1271. const long    val;
  1272. char * const    buf;
  1273. {
  1274.     register int    i;
  1275.     register long    shift;
  1276.  
  1277.     for (i = 0, shift = 24; i < 4; ++i, shift -= 8)
  1278.         buf[i] = val >> shift;
  1279. }
  1280.  
  1281. static void
  1282. puttzcode(val, fp)
  1283. const long    val;
  1284. FILE * const    fp;
  1285. {
  1286.     char    buf[4];
  1287.  
  1288.     convert(val, buf);
  1289.     (void) fwrite((void *) buf, (size_t) sizeof buf, (size_t) 1, fp);
  1290. }
  1291.  
  1292. static void
  1293. writezone(name)
  1294. const char * const    name;
  1295. {
  1296.     register FILE *        fp;
  1297.     register int        i, j;
  1298.     static char *        fullname;
  1299.     static struct tzhead    tzh;
  1300.  
  1301.     fullname = erealloc(fullname,
  1302.         (int) (strlen(directory) + 1 + strlen(name) + 1));
  1303.     (void) sprintf(fullname, "%s/%s", directory, name);
  1304.     if ((fp = fopen(fullname, "wb")) == NULL) {
  1305.         if (mkdirs(fullname) != 0)
  1306.             (void) exit(EXIT_FAILURE);
  1307.         if ((fp = fopen(fullname, "wb")) == NULL) {
  1308.             (void) fprintf(stderr, "%s: Can't create ", progname);
  1309.             (void) perror(fullname);
  1310.             (void) exit(EXIT_FAILURE);
  1311.         }
  1312.     }
  1313.     convert(eitol(typecnt), tzh.tzh_ttisgmtcnt);
  1314.     convert(eitol(typecnt), tzh.tzh_ttisstdcnt);
  1315.     convert(eitol(leapcnt), tzh.tzh_leapcnt);
  1316.     convert(eitol(timecnt), tzh.tzh_timecnt);
  1317.     convert(eitol(typecnt), tzh.tzh_typecnt);
  1318.     convert(eitol(charcnt), tzh.tzh_charcnt);
  1319. #define DO(field)    (void) fwrite((void *) tzh.field, \
  1320.         (size_t) sizeof tzh.field, (size_t) 1, fp)
  1321.     DO(tzh_reserved);
  1322.     DO(tzh_ttisgmtcnt);
  1323.     DO(tzh_ttisstdcnt);
  1324.     DO(tzh_leapcnt);
  1325.     DO(tzh_timecnt);
  1326.     DO(tzh_typecnt);
  1327.     DO(tzh_charcnt);
  1328. #undef DO
  1329.     for (i = 0; i < timecnt; ++i) {
  1330.         j = leapcnt;
  1331.         while (--j >= 0)
  1332.             if (ats[i] >= trans[j]) {
  1333.                 ats[i] = tadd(ats[i], corr[j]);
  1334.                 break;
  1335.             }
  1336.         puttzcode((long) ats[i], fp);
  1337.     }
  1338.     if (timecnt > 0)
  1339.         (void) fwrite((void *) types, (size_t) sizeof types[0],
  1340.             (size_t) timecnt, fp);
  1341.     for (i = 0; i < typecnt; ++i) {
  1342.         puttzcode((long) gmtoffs[i], fp);
  1343.         (void) putc(isdsts[i], fp);
  1344.         (void) putc(abbrinds[i], fp);
  1345.     }
  1346.     if (charcnt != 0)
  1347.         (void) fwrite((void *) chars, (size_t) sizeof chars[0],
  1348.             (size_t) charcnt, fp);
  1349.     for (i = 0; i < leapcnt; ++i) {
  1350.         if (roll[i]) {
  1351.             if (timecnt == 0 || trans[i] < ats[0]) {
  1352.                 j = 0;
  1353.                 while (isdsts[j])
  1354.                     if (++j >= typecnt) {
  1355.                         j = 0;
  1356.                         break;
  1357.                     }
  1358.             } else {
  1359.                 j = 1;
  1360.                 while (j < timecnt && trans[i] >= ats[j])
  1361.                     ++j;
  1362.                 j = types[j - 1];
  1363.             }
  1364.             puttzcode((long) tadd(trans[i], -gmtoffs[j]), fp);
  1365.         } else    puttzcode((long) trans[i], fp);
  1366.         puttzcode((long) corr[i], fp);
  1367.     }
  1368.     for (i = 0; i < typecnt; ++i)
  1369.         (void) putc(ttisstds[i], fp);
  1370.     for (i = 0; i < typecnt; ++i)
  1371.         (void) putc(ttisgmts[i], fp);
  1372.     if (ferror(fp) || fclose(fp)) {
  1373.         (void) fprintf(stderr, "%s: Write error on ", progname);
  1374.         (void) perror(fullname);
  1375.         (void) exit(EXIT_FAILURE);
  1376.     }
  1377. }
  1378.  
  1379. static void
  1380. doabbr(abbr, format, letters, isdst)
  1381. char * const        abbr;
  1382. const char * const    format;
  1383. const char * const    letters;
  1384. const int        isdst;
  1385. {
  1386.     if (strchr(format, '/') == NULL) {
  1387.         if (letters == NULL)
  1388.             (void) strcpy(abbr, format);
  1389.         else    (void) sprintf(abbr, format, letters);
  1390.     } else if (isdst)
  1391.         (void) strcpy(abbr, strchr(format, '/') + 1);
  1392.     else {
  1393.         (void) strcpy(abbr, format);
  1394.         *strchr(abbr, '/') = '\0';
  1395.     }
  1396. }
  1397.  
  1398. static void
  1399. outzone(zpfirst, zonecount)
  1400. const struct zone * const    zpfirst;
  1401. const int            zonecount;
  1402. {
  1403.     register const struct zone *    zp;
  1404.     register struct rule *        rp;
  1405.     register int            i, j;
  1406.     register int            usestart, useuntil;
  1407.     register time_t            starttime, untiltime;
  1408.     register long            gmtoff;
  1409.     register long            stdoff;
  1410.     register int            year;
  1411.     register long            startoff;
  1412.     register int            startisdst;
  1413.     register int            startttisstd;
  1414.     register int            startttisgmt;
  1415.     register int            type;
  1416.     char                startbuf[BUFSIZ];
  1417.  
  1418.     INITIALIZE(untiltime);
  1419.     INITIALIZE(starttime);
  1420.     INITIALIZE(startoff);
  1421.     /*
  1422.     ** Now. . .finally. . .generate some useful data!
  1423.     */
  1424.     timecnt = 0;
  1425.     typecnt = 0;
  1426.     charcnt = 0;
  1427.     /*
  1428.     ** A guess that may well be corrected later.
  1429.     */
  1430.     stdoff = 0;
  1431.     /*
  1432.     ** Thanks to Earl Chew (earl@dnd.icp.nec.com.au)
  1433.     ** for noting the need to unconditionally initialize startttisstd.
  1434.     */
  1435.     startttisstd = FALSE;
  1436.     startttisgmt = FALSE;
  1437.     for (i = 0; i < zonecount; ++i) {
  1438.         zp = &zpfirst[i];
  1439.         usestart = i > 0 && (zp - 1)->z_untiltime > min_time;
  1440.         useuntil = i < (zonecount - 1);
  1441.         if (useuntil && zp->z_untiltime <= min_time)
  1442.             continue;
  1443.         gmtoff = zp->z_gmtoff;
  1444.         eat(zp->z_filename, zp->z_linenum);
  1445.         startisdst = -1;
  1446.         if (zp->z_nrules == 0) {
  1447.             stdoff = zp->z_stdoff;
  1448.             doabbr(startbuf, zp->z_format,
  1449.                 (char *) NULL, stdoff != 0);
  1450.             type = addtype(oadd(zp->z_gmtoff, stdoff),
  1451.                 startbuf, stdoff != 0, startttisstd,
  1452.                 startttisgmt);
  1453.             if (usestart)
  1454.                 addtt(starttime, type);
  1455.             else if (stdoff != 0)
  1456.                 addtt(min_time, type);
  1457.         } else for (year = min_year; year <= max_year; ++year) {
  1458.             if (useuntil && year > zp->z_untilrule.r_hiyear)
  1459.                 break;
  1460.             /*
  1461.             ** Mark which rules to do in the current year.
  1462.             ** For those to do, calculate rpytime(rp, year);
  1463.             */
  1464.             for (j = 0; j < zp->z_nrules; ++j) {
  1465.                 rp = &zp->z_rules[j];
  1466.                 eats(zp->z_filename, zp->z_linenum,
  1467.                     rp->r_filename, rp->r_linenum);
  1468.                 rp->r_todo = year >= rp->r_loyear &&
  1469.                         year <= rp->r_hiyear &&
  1470.                         yearistype(year, rp->r_yrtype);
  1471.                 if (rp->r_todo)
  1472.                     rp->r_temp = rpytime(rp, year);
  1473.             }
  1474.             for ( ; ; ) {
  1475.                 register int    k;
  1476.                 register time_t    jtime, ktime;
  1477.                 register long    offset;
  1478.                 char        buf[BUFSIZ];
  1479.  
  1480.                 INITIALIZE(ktime);
  1481.                 if (useuntil) {
  1482.                     /*
  1483.                     ** Turn untiltime into GMT
  1484.                     ** assuming the current gmtoff and
  1485.                     ** stdoff values.
  1486.                     */
  1487.                     untiltime = zp->z_untiltime;
  1488.                     if (!zp->z_untilrule.r_todisgmt)
  1489.                         untiltime = tadd(untiltime,
  1490.                             -gmtoff);
  1491.                     if (!zp->z_untilrule.r_todisstd)
  1492.                         untiltime = tadd(untiltime,
  1493.                             -stdoff);
  1494.                 }
  1495.                 /*
  1496.                 ** Find the rule (of those to do, if any)
  1497.                 ** that takes effect earliest in the year.
  1498.                 */
  1499.                 k = -1;
  1500.                 for (j = 0; j < zp->z_nrules; ++j) {
  1501.                     rp = &zp->z_rules[j];
  1502.                     if (!rp->r_todo)
  1503.                         continue;
  1504.                     eats(zp->z_filename, zp->z_linenum,
  1505.                         rp->r_filename, rp->r_linenum);
  1506.                     offset = rp->r_todisgmt ? 0 : gmtoff;
  1507.                     if (!rp->r_todisstd)
  1508.                         offset = oadd(offset, stdoff);
  1509.                     jtime = rp->r_temp;
  1510.                     if (jtime == min_time ||
  1511.                         jtime == max_time)
  1512.                             continue;
  1513.                     jtime = tadd(jtime, -offset);
  1514.                     if (k < 0 || jtime < ktime) {
  1515.                         k = j;
  1516.                         ktime = jtime;
  1517.                     }
  1518.                 }
  1519.                 if (k < 0)
  1520.                     break;    /* go on to next year */
  1521.                 rp = &zp->z_rules[k];
  1522.                 rp->r_todo = FALSE;
  1523.                 if (useuntil && ktime >= untiltime)
  1524.                     break;
  1525.                 if (usestart) {
  1526.                     if (ktime < starttime) {
  1527.                     stdoff = rp->r_stdoff;
  1528.                     startoff = oadd(zp->z_gmtoff,
  1529.                         rp->r_stdoff);
  1530.                     doabbr(startbuf, zp->z_format,
  1531.                         rp->r_abbrvar,
  1532.                         rp->r_stdoff != 0);
  1533.                     startisdst = rp->r_stdoff != 0;
  1534.                     continue;
  1535.                     }
  1536.                     usestart = FALSE;
  1537.                     if (ktime != starttime) {
  1538.                     if (startisdst < 0 &&
  1539.                         zp->z_gmtoff !=
  1540.                         (zp - 1)->z_gmtoff) {
  1541.                         type = (timecnt == 0) ? 0 :
  1542.                             types[timecnt - 1];
  1543.                         startoff = oadd(gmtoffs[type],
  1544.                             -(zp - 1)->z_gmtoff);
  1545.                         startisdst = startoff != 0;
  1546.                         startoff = oadd(startoff,
  1547.                             zp->z_gmtoff);
  1548.                         (void) strcpy(startbuf,
  1549.                             &chars[abbrinds[type]]);
  1550.                     }
  1551.                     if (startisdst >= 0)
  1552. addtt(starttime, addtype(startoff, startbuf, startisdst, startttisstd,
  1553.     startttisgmt));
  1554.                     }
  1555.                 }
  1556.                 eats(zp->z_filename, zp->z_linenum,
  1557.                     rp->r_filename, rp->r_linenum);
  1558.                 doabbr(buf, zp->z_format, rp->r_abbrvar,
  1559.                     rp->r_stdoff != 0);
  1560.                 offset = oadd(zp->z_gmtoff, rp->r_stdoff);
  1561.                 type = addtype(offset, buf, rp->r_stdoff != 0,
  1562.                     rp->r_todisstd, rp->r_todisgmt);
  1563.                 addtt(ktime, type);
  1564.                 stdoff = rp->r_stdoff;
  1565.             }
  1566.         }
  1567.         /*
  1568.         ** Now we may get to set starttime for the next zone line.
  1569.         */
  1570.         if (useuntil) {
  1571.             starttime = tadd(zp->z_untiltime, -gmtoff);
  1572.             startttisstd = zp->z_untilrule.r_todisstd;
  1573.             startttisgmt = zp->z_untilrule.r_todisgmt;
  1574.             if (!startttisstd)
  1575.                 starttime = tadd(starttime, -stdoff);
  1576.         }
  1577.     }
  1578.     writezone(zpfirst->z_name);
  1579. }
  1580.  
  1581. static void
  1582. addtt(starttime, type)
  1583. const time_t    starttime;
  1584. const int    type;
  1585. {
  1586.     if (timecnt != 0 && type == types[timecnt - 1])
  1587.         return;    /* easy enough! */
  1588.     if (timecnt == 0 && type == 0 && isdsts[0] == 0)
  1589.         return; /* handled by default rule */
  1590.     if (timecnt >= TZ_MAX_TIMES) {
  1591.         error("too many transitions?!");
  1592.         (void) exit(EXIT_FAILURE);
  1593.     }
  1594.     ats[timecnt] = starttime;
  1595.     types[timecnt] = type;
  1596.     ++timecnt;
  1597. }
  1598.  
  1599. static int
  1600. addtype(gmtoff, abbr, isdst, ttisstd, ttisgmt)
  1601. const long        gmtoff;
  1602. const char * const    abbr;
  1603. const int        isdst;
  1604. const int        ttisstd;
  1605. const int        ttisgmt;
  1606. {
  1607.     register int    i, j;
  1608.  
  1609.     /*
  1610.     ** See if there's already an entry for this zone type.
  1611.     ** If so, just return its index.
  1612.     */
  1613.     for (i = 0; i < typecnt; ++i) {
  1614.         if (gmtoff == gmtoffs[i] && isdst == isdsts[i] &&
  1615.             strcmp(abbr, &chars[abbrinds[i]]) == 0 &&
  1616.             ttisstd == ttisstds[i] &&
  1617.             ttisgmt == ttisgmts[i])
  1618.                 return i;
  1619.     }
  1620.     /*
  1621.     ** There isn't one; add a new one, unless there are already too
  1622.     ** many.
  1623.     */
  1624.     if (typecnt >= TZ_MAX_TYPES) {
  1625.         error("too many local time types");
  1626.         (void) exit(EXIT_FAILURE);
  1627.     }
  1628.     gmtoffs[i] = gmtoff;
  1629.     isdsts[i] = isdst;
  1630.     ttisstds[i] = ttisstd;
  1631.     ttisgmts[i] = ttisgmt;
  1632.  
  1633.     for (j = 0; j < charcnt; ++j)
  1634.         if (strcmp(&chars[j], abbr) == 0)
  1635.             break;
  1636.     if (j == charcnt)
  1637.         newabbr(abbr);
  1638.     abbrinds[i] = j;
  1639.     ++typecnt;
  1640.     return i;
  1641. }
  1642.  
  1643. static void
  1644. leapadd(t, positive, rolling, count)
  1645. const time_t    t;
  1646. const int    positive;
  1647. const int    rolling;
  1648. int        count;
  1649. {
  1650.     register int    i, j;
  1651.  
  1652.     if (leapcnt + (positive ? count : 1) > TZ_MAX_LEAPS) {
  1653.         error("too many leap seconds");
  1654.         (void) exit(EXIT_FAILURE);
  1655.     }
  1656.     for (i = 0; i < leapcnt; ++i)
  1657.         if (t <= trans[i]) {
  1658.             if (t == trans[i]) {
  1659.                 error("repeated leap second moment");
  1660.                 (void) exit(EXIT_FAILURE);
  1661.             }
  1662.             break;
  1663.         }
  1664.     do {
  1665.         for (j = leapcnt; j > i; --j) {
  1666.             trans[j] = trans[j - 1];
  1667.             corr[j] = corr[j - 1];
  1668.             roll[j] = roll[j - 1];
  1669.         }
  1670.         trans[i] = t;
  1671.         corr[i] = positive ? 1L : eitol(-count);
  1672.         roll[i] = rolling;
  1673.         ++leapcnt;
  1674.     } while (positive && --count != 0);
  1675. }
  1676.  
  1677. static void
  1678. adjleap P((void))
  1679. {
  1680.     register int    i;
  1681.     register long    last = 0;
  1682.  
  1683.     /*
  1684.     ** propagate leap seconds forward
  1685.     */
  1686.     for (i = 0; i < leapcnt; ++i) {
  1687.         trans[i] = tadd(trans[i], last);
  1688.         last = corr[i] += last;
  1689.     }
  1690. }
  1691.  
  1692. static int
  1693. yearistype(year, type)
  1694. const int        year;
  1695. const char * const    type;
  1696. {
  1697.     static char *    buf;
  1698.     int        result;
  1699.  
  1700.     if (type == NULL || *type == '\0')
  1701.         return TRUE;
  1702.     buf = erealloc(buf, (int) (132 + strlen(yitcommand) + strlen(type)));
  1703.     (void) sprintf(buf, "%s %d %s", yitcommand, year, type);
  1704.     result = system(buf);
  1705.     if (result == 0)
  1706.         return TRUE;
  1707.     if (result == (1 << 8))
  1708.         return FALSE;
  1709.     error("Wild result from command execution");
  1710.     (void) fprintf(stderr, "%s: command was '%s', result was %d\n",
  1711.         progname, buf, result);
  1712.     for ( ; ; )
  1713.         (void) exit(EXIT_FAILURE);
  1714. }
  1715.  
  1716. static int
  1717. lowerit(a)
  1718. int    a;
  1719. {
  1720.     a = (unsigned char) a;
  1721.     return (isascii(a) && isupper(a)) ? tolower(a) : a;
  1722. }
  1723.  
  1724. static int
  1725. ciequal(ap, bp)        /* case-insensitive equality */
  1726. register const char *    ap;
  1727. register const char *    bp;
  1728. {
  1729.     while (lowerit(*ap) == lowerit(*bp++))
  1730.         if (*ap++ == '\0')
  1731.             return TRUE;
  1732.     return FALSE;
  1733. }
  1734.  
  1735. static int
  1736. itsabbr(abbr, word)
  1737. register const char *    abbr;
  1738. register const char *    word;
  1739. {
  1740.     if (lowerit(*abbr) != lowerit(*word))
  1741.         return FALSE;
  1742.     ++word;
  1743.     while (*++abbr != '\0')
  1744.         do {
  1745.             if (*word == '\0')
  1746.                 return FALSE;
  1747.         } while (lowerit(*word++) != lowerit(*abbr));
  1748.     return TRUE;
  1749. }
  1750.  
  1751. static const struct lookup *
  1752. byword(word, table)
  1753. register const char * const        word;
  1754. register const struct lookup * const    table;
  1755. {
  1756.     register const struct lookup *    foundlp;
  1757.     register const struct lookup *    lp;
  1758.  
  1759.     if (word == NULL || table == NULL)
  1760.         return NULL;
  1761.     /*
  1762.     ** Look for exact match.
  1763.     */
  1764.     for (lp = table; lp->l_word != NULL; ++lp)
  1765.         if (ciequal(word, lp->l_word))
  1766.             return lp;
  1767.     /*
  1768.     ** Look for inexact match.
  1769.     */
  1770.     foundlp = NULL;
  1771.     for (lp = table; lp->l_word != NULL; ++lp)
  1772.         if (itsabbr(word, lp->l_word))
  1773.             if (foundlp == NULL)
  1774.                 foundlp = lp;
  1775.             else    return NULL;    /* multiple inexact matches */
  1776.     return foundlp;
  1777. }
  1778.  
  1779. static char **
  1780. getfields(cp)
  1781. register char *    cp;
  1782. {
  1783.     register char *        dp;
  1784.     register char **    array;
  1785.     register int        nsubs;
  1786.  
  1787.     if (cp == NULL)
  1788.         return NULL;
  1789.     array = (char **) (void *)
  1790.         emalloc((int) ((strlen(cp) + 1) * sizeof *array));
  1791.     nsubs = 0;
  1792.     for ( ; ; ) {
  1793.         while (isascii(*cp) && isspace((unsigned char) *cp))
  1794.             ++cp;
  1795.         if (*cp == '\0' || *cp == '#')
  1796.             break;
  1797.         array[nsubs++] = dp = cp;
  1798.         do {
  1799.             if ((*dp = *cp++) != '"')
  1800.                 ++dp;
  1801.             else while ((*dp = *cp++) != '"')
  1802.                 if (*dp != '\0')
  1803.                     ++dp;
  1804.                 else    error("Odd number of quotation marks");
  1805.         } while (*cp != '\0' && *cp != '#' &&
  1806.             (!isascii(*cp) || !isspace((unsigned char) *cp)));
  1807.         if (isascii(*cp) && isspace((unsigned char) *cp))
  1808.             ++cp;
  1809.         *dp = '\0';
  1810.     }
  1811.     array[nsubs] = NULL;
  1812.     return array;
  1813. }
  1814.  
  1815. static long
  1816. oadd(t1, t2)
  1817. const long    t1;
  1818. const long    t2;
  1819. {
  1820.     register long    t;
  1821.  
  1822.     t = t1 + t2;
  1823.     if ((t2 > 0 && t <= t1) || (t2 < 0 && t >= t1)) {
  1824.         error("time overflow");
  1825.         (void) exit(EXIT_FAILURE);
  1826.     }
  1827.     return t;
  1828. }
  1829.  
  1830. static time_t
  1831. tadd(t1, t2)
  1832. const time_t    t1;
  1833. const long    t2;
  1834. {
  1835.     register time_t    t;
  1836.  
  1837.     if (t1 == max_time && t2 > 0)
  1838.         return max_time;
  1839.     if (t1 == min_time && t2 < 0)
  1840.         return min_time;
  1841.     t = t1 + t2;
  1842.     if ((t2 > 0 && t <= t1) || (t2 < 0 && t >= t1)) {
  1843.         error("time overflow");
  1844.         (void) exit(EXIT_FAILURE);
  1845.     }
  1846.     return t;
  1847. }
  1848.  
  1849. /*
  1850. ** Given a rule, and a year, compute the date - in seconds since January 1,
  1851. ** 1970, 00:00 LOCAL time - in that year that the rule refers to.
  1852. */
  1853.  
  1854. static time_t
  1855. rpytime(rp, wantedy)
  1856. register const struct rule * const    rp;
  1857. register const int            wantedy;
  1858. {
  1859.     register int    y, m, i;
  1860.     register long    dayoff;            /* with a nod to Margaret O. */
  1861.     register time_t    t;
  1862.  
  1863.     if (wantedy == INT_MIN)
  1864.         return min_time;
  1865.     if (wantedy == INT_MAX)
  1866.         return max_time;
  1867.     dayoff = 0;
  1868.     m = TM_JANUARY;
  1869.     y = EPOCH_YEAR;
  1870.     while (wantedy != y) {
  1871.         if (wantedy > y) {
  1872.             i = len_years[isleap(y)];
  1873.             ++y;
  1874.         } else {
  1875.             --y;
  1876.             i = -len_years[isleap(y)];
  1877.         }
  1878.         dayoff = oadd(dayoff, eitol(i));
  1879.     }
  1880.     while (m != rp->r_month) {
  1881.         i = len_months[isleap(y)][m];
  1882.         dayoff = oadd(dayoff, eitol(i));
  1883.         ++m;
  1884.     }
  1885.     i = rp->r_dayofmonth;
  1886.     if (m == TM_FEBRUARY && i == 29 && !isleap(y)) {
  1887.         if (rp->r_dycode == DC_DOWLEQ)
  1888.             --i;
  1889.         else {
  1890.             error("use of 2/29 in non leap-year");
  1891.             (void) exit(EXIT_FAILURE);
  1892.         }
  1893.     }
  1894.     --i;
  1895.     dayoff = oadd(dayoff, eitol(i));
  1896.     if (rp->r_dycode == DC_DOWGEQ || rp->r_dycode == DC_DOWLEQ) {
  1897.         register long    wday;
  1898.  
  1899. #define LDAYSPERWEEK    ((long) DAYSPERWEEK)
  1900.         wday = eitol(EPOCH_WDAY);
  1901.         /*
  1902.         ** Don't trust mod of negative numbers.
  1903.         */
  1904.         if (dayoff >= 0)
  1905.             wday = (wday + dayoff) % LDAYSPERWEEK;
  1906.         else {
  1907.             wday -= ((-dayoff) % LDAYSPERWEEK);
  1908.             if (wday < 0)
  1909.                 wday += LDAYSPERWEEK;
  1910.         }
  1911.         while (wday != eitol(rp->r_wday))
  1912.             if (rp->r_dycode == DC_DOWGEQ) {
  1913.                 dayoff = oadd(dayoff, (long) 1);
  1914.                 if (++wday >= LDAYSPERWEEK)
  1915.                     wday = 0;
  1916.                 ++i;
  1917.             } else {
  1918.                 dayoff = oadd(dayoff, (long) -1);
  1919.                 if (--wday < 0)
  1920.                     wday = LDAYSPERWEEK - 1;
  1921.                 --i;
  1922.             }
  1923.         if (i < 0 || i >= len_months[isleap(y)][m]) {
  1924.             error("no day in month matches rule");
  1925.             (void) exit(EXIT_FAILURE);
  1926.         }
  1927.     }
  1928.     if (dayoff < 0 && !TIME_T_SIGNED)
  1929.         return min_time;
  1930.     t = (time_t) dayoff * SECSPERDAY;
  1931.     /*
  1932.     ** Cheap overflow check.
  1933.     */
  1934.     if (t / SECSPERDAY != dayoff)
  1935.         return (dayoff > 0) ? max_time : min_time;
  1936.     return tadd(t, rp->r_tod);
  1937. }
  1938.  
  1939. static void
  1940. newabbr(string)
  1941. const char * const    string;
  1942. {
  1943.     register int    i;
  1944.  
  1945.     i = strlen(string) + 1;
  1946.     if (charcnt + i > TZ_MAX_CHARS) {
  1947.         error("too many, or too long, time zone abbreviations");
  1948.         (void) exit(EXIT_FAILURE);
  1949.     }
  1950.     (void) strcpy(&chars[charcnt], string);
  1951.     charcnt += eitol(i);
  1952. }
  1953.  
  1954. static int
  1955. mkdirs(argname)
  1956. char * const    argname;
  1957. {
  1958.     register char *    name;
  1959.     register char *    cp;
  1960.  
  1961.     if (argname == NULL || *argname == '\0')
  1962.         return 0;
  1963.     cp = name = ecpyalloc(argname);
  1964.     while ((cp = strchr(cp + 1, '/')) != 0) {
  1965.         *cp = '\0';
  1966. #ifndef unix
  1967.         /*
  1968.         ** DOS drive specifier?
  1969.         */
  1970.         if (isalpha((unsigned char) name[0]) &&
  1971.             name[1] == ':' && name[2] != '\0') {
  1972.                 *cp = '/';
  1973.                 continue;
  1974.         }
  1975. #endif /* !defined unix */
  1976.         if (!itsdir(name)) {
  1977.             /*
  1978.             ** It doesn't seem to exist, so we try to create it.
  1979.             */
  1980.             if (mkdir(name, 0755) != 0) {
  1981.                 (void) fprintf(stderr,
  1982.                     "%s: Can't create directory ",
  1983.                     progname);
  1984.                 (void) perror(name);
  1985.                 ifree(name);
  1986.                 return -1;
  1987.             }
  1988.         }
  1989.         *cp = '/';
  1990.     }
  1991.     ifree(name);
  1992.     return 0;
  1993. }
  1994.  
  1995. static long
  1996. eitol(i)
  1997. const int    i;
  1998. {
  1999.     long    l;
  2000.  
  2001.     l = i;
  2002.     if ((i < 0 && l >= 0) || (i == 0 && l != 0) || (i > 0 && l <= 0)) {
  2003.         (void) fprintf(stderr,
  2004.             "%s: %d did not sign extend correctly\n",
  2005.             progname, i);
  2006.         (void) exit(EXIT_FAILURE);
  2007.     }
  2008.     return l;
  2009. }
  2010.  
  2011. /*
  2012. ** UNIX was a registered trademark of UNIX System Laboratories in 1993.
  2013. */
  2014.